3.11 Виджеты. Card
3 из 3 шагов пройдено

 Виджеты. Card

➡️ Скачать презентацию. Flutter Card
➡️ Ссылка на репозиторий с кодом этого урока

Создание карточки Card Material 3

Виджет Card во Flutter используется для отображения элементов в виде карточек с закругленными углами и тенями. Часто используется для отображения связанных элементов (карточки товаров, карточки профиля).
https://m3.material.io/components/cards/guidelines

Основные особенности:

  • Карточки имеют тень, что придаёт глубину и выделяет их. Изменение свойства elevation карты позволяет контролировать эффект тени.
  • Закругленные углы создают более современный и эстетичный вид.
  • Card из библиотеки Material содержит связанные фрагменты информации и может быть составлена практически из любого виджета, но часто используется вместе с ListTile()
  • По умолчанию карта сжимает свой размер до 0 на 0 пикселей. Можно использовать SizedBox, чтобы ограничить размер карты.
  • Содержимое Card не прокручивается

Виджет Card

  • В папку widgets добавим файл card_widget.dart
  • В файле card_widget.dart добавим новый виджет CardExample()
  • ⭕ В файле main.dart внутри виджета MyApp() в параметр body передаём CardExample()
import 'package:flutter/material.dart';

class CardExample extends StatelessWidget {
  const CardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Card();
  }
}

Основные параметры Card

color: задает цвет карточки.
elevation: регулирует высоту тени. Чем больше значение, тем сильнее тень.
shape: определяет форму карточки, в том числе радиус закругления углов.
margin: отступы вокруг карточки.
child: основной содержимый виджет внутри карточки.
shadowColor: цвет тени, который отображается вокруг карточки.

Примеры использования виджета Card

Простая карточка с текстом.
Карточка имеет базовую тень и закругленные углы по умолчанию.

Файл card_widget.dart

import 'package:flutter/material.dart';

class CardExample extends StatelessWidget {
  const CardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Text(
            'Карточка с текстом',
            style: TextStyle(fontSize: 18),
          ),
        ),
      ),
    );
  }
}

Добавим цвет для карточки и для тени, сделаем карточку выше через elevation

Файл card_widget.dart

Card(
  color: Colors.lightBlue[50],
  elevation: 10,
  shadowColor: Colors.blueAccent,
  child: Padding(
    padding: EdgeInsets.all(16.0),
    child: Text(
      'Карточка с цветом и тенями',
      style: TextStyle(fontSize: 18),
    ),
  ),
),

Комплексный пример создания карточки

Файл card_widget.dart 

import 'package:flutter/material.dart';

class CardExample extends StatelessWidget {
  const CardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        elevation: 2, // Высота тени
        color: Colors.white, // Цвет фона карточки

        // По умолчанию размеры карточки 0 на 0
        // Обернём в SizedBox и укажем размеры вручную
        child: SizedBox(
          width: 310, // Ширина карточки
          child: Column( // Содержимое карточки будет располагаться в колонке
            mainAxisSize: MainAxisSize.min, // Высота ужмётся под содержимое
            children: [
              Image.asset(
                'assets/images/fd.png',
              ),
              ListTile(
                title: Text("Flutter Конференция"),
                subtitle: Text("Самое крутое мероприятие в году"),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Виджет ClipRRect

Чтобы скруглить верхние углы у изображения нужно его обернуть в виджет ClipRRect()

Он позволяет обрезать (обтекать) дочерний виджет, применяя закругленные углы (borderRadius). Он полезен, когда нужно создать округлые изображения, кнопки или контейнеры.

Основные параметры:
borderRadius: устанавливает радиус скругления углов.
clipBehavior: определяет, как обрезается содержимое.
child: дочерний виджет, который будет обрезан.

Файл card_widget.dart 

class CardExample extends StatelessWidget {
  const CardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        elevation: 2, // Высота тени
        color: Colors.white, // Цвет фона карточки
        // По умолчанию размеры карточки 0 на 0
        // Обернём в SizedBox и укажем размеры вручную
        child: SizedBox(
          width: 310, // Ширина карточки
          child: Column(
            // Содержимое карточки будет располагаться в колонке
            mainAxisSize: MainAxisSize.min, // Высота ужмётся под содержимое
            children: [
              ClipRRect(
                borderRadius: const BorderRadius.only(
                  topLeft: Radius.circular(12), // Радиус углов сверху слева
                  topRight: Radius.circular(12), // Радиус углов сверху справа
                ),
                child: Image.asset(
                  'assets/images/fd.png',
                  width: double.infinity, // Максимально возможная ширина
                  height: 180, // Фиксированная высота изображения
                  fit: BoxFit.cover, // Заполняет все пространство
                ),
              ),
              ListTile(
                title: Text("Flutter Конференция"),
                subtitle: Text("Самое крутое мероприятие в году"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

Виджет ListTile

Удобный виджет для оформления элемента списка. Он объединяет заголовок, подзаголовок, иконки, leading и trailing виджеты в одном элементе.

В ListTile добавим кнопку "Купить билеты"

Основные параметры:
leading: виджет, который отображается слева (обычно иконка или аватарка).
title: основной заголовок.
subtitle: подзаголовок (второстепенный текст).
trailing: виджет, который справа (обычно иконка или кнопка).
onTap: обработчик нажатия.
tileColor: цвет фона.
shape: форма элемента (например, скругленные углы).
selected: если true, элемент выделяется цветом selectedTileColor.

В subtitle можно передать колонку, в колонке расположить Text и ElevationButton

Полностью код карточки

Файл card_widget.dart

import 'package:flutter/material.dart';

class CardExample extends StatelessWidget {
  const CardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        elevation: 2, // Высота тени
        color: Colors.white, // Цвет фона карточки
        // По умолчанию размеры карточки 0 на 0
        // Обернём в SizedBox и укажем размеры вручную
        child: SizedBox(
          width: 310, // Ширина карточки
          child: Column(
            // Содержимое карточки будет располагаться в колонке
            mainAxisSize: MainAxisSize.min, // Высота ужмётся под содержимое
            children: [
              ClipRRect(
                borderRadius: const BorderRadius.only(
                  topLeft: Radius.circular(12), // Радиус углов сверху слева
                  topRight: Radius.circular(12), // Радиус углов сверху справа
                ),
                child: Image.asset(
                  'assets/images/fd.png',
                  width: double.infinity, // Максимально возможная ширина
                  height: 180, // Фиксированная высота изображения
                  fit: BoxFit.cover, // Заполняет все пространство
                ),
              ),
              ListTile(
                title: Text("Flutter Конференция"),

                subtitle: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text("Самое крутое мероприятие в году"),

                    SizedBox(height: 8),

                    Padding(
                      padding: const EdgeInsets.only(bottom: 8.0),
                      child: ElevatedButton(
                        onPressed: () {},
                        child: const Text("Купить билеты"),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Виды Card

Есть ещё два вида карточки

  1. С обводкой
  2. С заполнением
class CardTypesExample extends StatelessWidget {
  const CardTypesExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SizedBox(
        width: 320,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Карточка с обводкой Card.outlined
            Card.outlined(
              child: ListTile(
                leading: Icon(Icons.favorite),
                title: Text("Карточка с обводкой"),
                subtitle: Text("Card.outlined"),
              ),
            ),
        
            // Карточка с закрашеным фоном Card.filled
            Card.filled(
              child: ListTile(
                leading: Icon(Icons.favorite),
                title: Text("Карточка с заполнением"),
                subtitle: Text("Card.filled"),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Переделаем пример с роллами

class RollCard extends StatelessWidget {
  final double height;
  const RollCard({super.key, this.height = 220});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 190,
      child: Card(
        margin: EdgeInsets.all(8),
        color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            ClipRRect(
              borderRadius: const BorderRadius.only(
                topLeft: Radius.circular(12), 
                topRight: Radius.circular(12), 
              ),
              child: Image.asset(
                "assets/images/sushi.jpg",
                width: double.infinity,
                height: 100,
                fit: BoxFit.cover,
              ),
            ),
            Expanded(
              child: ListTile(
                title: Text("Вкусные Роллы"),
                subtitle: Text(
                  "Огурец, креветка, сыр",
                  style: TextStyle(fontSize: 10),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(left: 6),
              child: TextButton(
                onPressed: () {},
                child: Text("Купить"),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий